/*
 *  Copyright 2008 The MITRE Corporation (http://www.mitre.org/). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.mitre.lattice.graph;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.Properties;

import org.jgraph.JGraph;
import org.jgraph.graph.CellMapper;
import org.jgraph.graph.CellViewRenderer;
import org.jgraph.graph.VertexRenderer;
import org.jgraph.graph.VertexView;
import org.mitre.mrald.util.Config;
/**
 *  Class that contains any functions that deal with Graphing of the Lattice
 *  objects, using JGraph as a graphical interface.
 *
 *@author     ghamilton
 *@created    December 12, 2003
 */
public class EllipseView extends VertexView
{
    public static EllipseRenderer renderer = new EllipseRenderer();


    /**
     *  Constructor for the EllipseView object
     *
     *@param  cell   Description of the Parameter
     *@param  graph  Description of the Parameter
     *@param  cm     Description of the Parameter
     */
    public EllipseView( Object cell, JGraph graph, CellMapper cm )
    {
        super( cell, graph, cm );
        //MraldOutFile.logToFile( Config.getProperty("LOGFILE") , "EllipseView : Constructor " );

    }


    /**
     *  Returns the intersection of the bounding rectangle and the straight line
     *  between the source and the specified point p. The specified point is
     *  expected not to intersect the bounds.
     *
     *@param  source  Description of the Parameter
     *@param  p       Description of the Parameter
     *@return         The perimeterPoint value
     */
    public Point2D getPerimeterPoint( Point2D source, Point2D p )
    {
        //MraldOutFile.logToFile( Config.getProperty("LOGFILE") , "EllipseView : getPerimeterPoint " );
       java.awt.geom.Rectangle2D r = getBounds();

        double x = r.getX();
        double y = r.getY();
        double a = ( r.getWidth() + 1 ) / 2;
        double b = ( r.getHeight() + 1 ) / 2;

        // x0,y0 - center of ellipse
        double x0 = x + a;
        double y0 = y + b;

        // x1, y1 - point
        double x1 = p.getX();
        double y1 = p.getY();

        // calculate straight line equation through point and ellipse center
        // y = d * x + h
        double dx = x1 - x0;
        double dy = y1 - y0;

        if ( dx == 0 )
        {
            return new Point( ( int ) x0, ( int ) ( y0 + b * dy / Math.abs( dy ) ) );
        }

        double d = dy / dx;
        double h = y0 - d * x0;

        // calculate intersection
        double e = a * a * d * d + b * b;
        double f = -2 * x0 * e;
        double g = a * a * d * d * x0 * x0 + b * b * x0 * x0 - a * a * b * b;

        double det = Math.sqrt( f * f - 4 * e * g );

        // two solutions (perimeter points)
        double xout1 = ( -f + det ) / ( 2 * e );
        double xout2 = ( -f - det ) / ( 2 * e );
        double yout1 = d * xout1 + h;
        double yout2 = d * xout2 + h;

        double dist1 = Math.sqrt( Math.pow( ( xout1 - x1 ), 2 )
                 + Math.pow( ( yout1 - y1 ), 2 ) );
        double dist2 = Math.sqrt( Math.pow( ( xout2 - x1 ), 2 )
                 + Math.pow( ( yout2 - y1 ), 2 ) );

        // correct solution
        double xout;

        // correct solution
        double yout;

        if ( dist1 < dist2 )
        {
            xout = xout1;
            yout = yout1;
        }
        else
        {
            xout = xout2;
            yout = yout2;
        }
        return getAttributes().createPoint( xout, yout );
        //return new Point((int)xout, (int)yout);
    }


    /**
     *  Gets the renderer attribute of the EllipseView object
     *
     *@return    The renderer value
     */
    public CellViewRenderer getRenderer()
    {
        return renderer;
    }


    /**
     *  Description of the Class
     *
     *@author     ghamilton
     *@created    August 19, 2004
     */
    public static class EllipseRenderer extends VertexRenderer
    {

        /**
         *  Description of the Method
         *
         *@param  g  Description of the Parameter
         */
        public void paint( Graphics g )
        {

		        int b = borderWidth;
			Graphics2D g2 = (Graphics2D) g;
			Dimension d = getSize();

			String type="Default";
                        Properties props = Config.getLatticeFactory().getProperties();

			String temp = props.getProperty(type + "ColorEnd");

			temp = temp.substring(temp.indexOf("(") + 1, temp.length() - 1);

			String[] nodeEndInts = temp.split(",");

			temp = props.getProperty(type + "ColorStart");
			temp = temp.substring(temp.indexOf("(") + 1, temp.length() - 1);

			String[] nodeStartInts = temp.split(",");

			Color nodeEndCol = new Color(Integer.parseInt(nodeEndInts[0].trim()), Integer.parseInt(nodeEndInts[1].trim()), Integer.parseInt(nodeEndInts[2].trim()));
			Color nodeStartCol = new Color(Integer.parseInt(nodeStartInts[0].trim()), Integer.parseInt(nodeStartInts[1].trim()), Integer.parseInt(nodeStartInts[2].trim()));

			GradientPaint nodeCol = new GradientPaint(b - 1, b - 1, nodeStartCol, d.width - b, d.height - b, nodeEndCol);

			boolean tmp = selected;

			if (super.isOpaque())
			{
				g2.setPaint(nodeCol);

				g2.fill(new Ellipse2D.Double(b - 1, b - 1, d.width - b, d.height - b));

				//g.fillOval(b - 1, b - 1, d.width - b, d.height - b);

			}
            try
            {
                //setBorder(BorderFactory.createRaisedBevelBorder());
                setBorder( null );
                setOpaque( false );
                selected = false;
                super.paint( g );
            }
            finally
            {
                selected = tmp;
            }
            if ( bordercolor != null )
            {
                g.setColor( bordercolor );
                g2.setStroke( new BasicStroke( b ) );
                g.drawOval( b - 1, b - 1, d.width - b, d.height - b );
                //g.drawRoundRect(b - 1, b - 1, d.width - b, d.height - b, d.width/3, d.height/3);
            }
            if ( selected )
            {
                //g2.setStroke(GraphConstants.SELECTION_STROKE);
                g2.setStroke( new BasicStroke( b ) );
                g.setColor( graph.getHighlightColor() );
                g.drawOval( b - 1, b - 1, d.width - b, d.height - b );
                //g.drawRoundRect(b - 1, b - 1, d.width - b, d.height - b, d.width/3, d.height/3);
            }
        }
    }
}

